package com.tengju.motivation.infrastructure.repository.activity;

import com.google.common.collect.Lists;
import com.tengju.motivation.domain.model.activity.*;
import com.tengju.motivation.domain.shared.BasePage;
import com.tengju.motivation.infrastructure.external.ActivityExternalService;
import com.tengju.motivation.infrastructure.persistence.mybatis.dataobject.MotivationActivityTargetDetailDO;
import com.tengju.motivation.infrastructure.persistence.mybatis.mapper.MotivationActivityTargetDetailMapper;
import com.tengju.motivation.infrastructure.repository.activity.convert.ActivityTargetConvert;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Repository
@RequiredArgsConstructor(onConstructor_ = {@Autowired})
public class ActivityRepositoryImpl implements ActivityRepository {

    private final ActivityExternalService activityExternalService;
    private final MotivationActivityTargetDetailMapper targetDetailMapper;


    @Override
    public List<Activity> getActivityList(String name, LocalDateTime sinceDate) {
        List<Activity> matchedActivities = activityExternalService.getActivityBriefList(name, sinceDate);
        List<Long> activityIds = Optional.ofNullable(matchedActivities)
                .map(list -> list.stream()
                        .map(Activity::getActivityId)
                        .map(ActivityId::getValue)
                        .collect(Collectors.toList()))
                .orElse(new ArrayList<>());
        if (!CollectionUtils.isEmpty(activityIds)) {
            return activityExternalService.getActivitiesById(activityIds.stream()
                    .map(ActivityId::new)
                    .collect(Collectors.toList()));
        } else {
            return null;
        }
    }

    @Override
    public BasePage<Activity> getActivityList(String name, int offset, int limit) {
        List<Long> activityIds = null;
        //命中名字的活动ID
        if (!StringUtils.isEmpty(name)) {
            List<Activity> matchedActivities = activityExternalService.getActivityBriefList(name, null);
            activityIds = Optional.ofNullable(matchedActivities)
                    .map(list -> list.stream()
                            .map(Activity::getActivityId)
                            .map(ActivityId::getValue)
                            .collect(Collectors.toList()))
                    .orElse(new ArrayList<>());
        }

        //按创建时间排序的分页已配置的活动id
        int total = targetDetailMapper.countActivityId(activityIds);
        //按创建时间排序的分页已配置的活动id
        activityIds = targetDetailMapper.getActivityIds(activityIds, (offset - 1) * limit, limit);

        if (!CollectionUtils.isEmpty(activityIds)) {
            List<Activity> activities = activityExternalService.getActivitiesById(activityIds.stream()
                    .map(ActivityId::new)
                    .collect(Collectors.toList())
            );
            BasePage<Activity> pageData = new BasePage<>();
            pageData.setDatas(activities);
            pageData.setTotal(total);
            pageData.setLimit(limit);
            pageData.setCurrPageNo(offset);
            return pageData;
        } else {
            return null;
        }
    }

    @Override
    public Activity getActivityById(ActivityId activityId) {
        if (activityId == null) {
            return null;
        }
        return activityExternalService.getActivity(activityId);
    }

    @Override
    public List<Activity> getActivityById(List<ActivityId> activityIds) {
        if (CollectionUtils.isEmpty(activityIds)) {
            return Collections.emptyList();
        }
        List<Activity> activityList = activityExternalService.getActivitiesById(activityIds);
        return Optional.ofNullable(activityList).orElse(Collections.emptyList());
    }

    @Override
    public int countTarget(ActivityId activityId) {
        return targetDetailMapper.countTarget(activityId.getValue());
    }

    @Override
    public List<ActivityTarget> getTargetList(ActivityId activityId) {

        List<MotivationActivityTargetDetailDO> detailDOs = targetDetailMapper.listTargets(activityId.getValue());

        return Optional.ofNullable(detailDOs)
                .map(details -> details.stream()
                        .map(ActivityTargetConvert::doToDomain)
                        .collect(Collectors.toList()))
                .orElse(new ArrayList<>());
    }

    @Override
    public void delete(ActivityId activityId) {
        targetDetailMapper.deleteByActivityId(activityId.getValue());
    }

    @Override
    public List<Long> listNoEndActivityIds(LocalDate activityEndDate) {
        return targetDetailMapper.listNoEndActivityIds(activityEndDate);
    }

    @Override
    public List<Long> listValidTimeActivityIds(LocalDate activityStartDate, LocalDate activityEndDate) {
        return targetDetailMapper.listValidTimeActivityIds(activityStartDate, activityEndDate);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(List<ActivityTarget> targets) {
        if (CollectionUtils.isEmpty(targets)) {
            return;
        }
        targetDetailMapper.batchInsert(targets.stream()
                .map(ActivityTargetConvert::domainToDo)
                .collect(Collectors.toList()));
    }

    @Override
    public void update(ActivityTarget target) {
        targetDetailMapper.update(ActivityTargetConvert.domainToDo(target));
    }

    @Override
    public void remove(List<TargetId> targetIds) {
        if(!CollectionUtils.isEmpty(targetIds)){
            targetDetailMapper.delete(targetIds.stream()
                    .map(TargetId::getValue)
                    .collect(Collectors.toList()));
        }
    }
}
